<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>撤销小教程</title>
    <style>
        html {
            background: pink;
        }
        .circleBox {
            display: flex;
        }

        .circle {
            margin: 10px;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            cursor: pointer;
        }

        .red {
            background: red;
        }

        .green {
            background: green;
        }

        .blue {
            background: blue;
        }

        .undoList,
        .rollbackList {
            display: flex;
            flex-flow: column-reverse;
            margin-right: 20px;
            width: 70px;
            height: 450px;
            border: 1px solid black;
        }

        .listBox {
            display: flex;
        }
    </style>
</head>

<body>
    <div id="app">
        <main>
            <div>
                点击添加：
                <div class="circleBox">
                    <div class="red circle" @click="onClickCircle('red')"></div>
                    <div class="green circle" @click="onClickCircle('green')"></div>
                    <div class="blue circle" @click="onClickCircle('blue')"></div>
                </div>
            </div>

            <div>
                <button @click="onUndo">撤销</button>
                <button @click="onBack">回退</button>
            </div>
            <div>
                <div>
                    <p> 当前的视图</p>
                    <div :class="currentView" class="circle"></div>
                </div>
                <div class="listBox">
                    <div>
                        <p>可撤銷列表</p>
                        <div class="undoList">
                            <div v-for="type in undoList" :class="type" class="circle"></div>
                        </div>
                    </div>

                    <div>
                        <p>可回退列表</p>
                        <div class="rollbackList">
                            <div v-for="type in rollbackList" :class="type" class="circle"></div>
                        </div>
                    </div>
                </div>
            </div>
        </main>

    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script>
        window.onload = function () {
            var record = createRecord();
            var app = new Vue({
                el: '#app',
                data: {
                    currentView: "",
                    undoList: [],
                    rollbackList: []
                },
                methods: {
                    onClickCircle(type) {
                        record.addRecord(type);
                        this.updateData();
                    },
                    onUndo() {
                        record.undoRecord();
                        this.updateData();
                    },
                    onBack() {
                        record.rollbackRecord();
                        this.updateData();
                    },
                    updateData() {
                        this.currentView = record.getTopValue();
                        this.undoList = record.getUndoStack();
                        this.rollbackList = record.getrollbackStack();
                    }
                }
            })

            function createRecord() {
                let undoStack = createStack();
                let rollbackStack = createStack();
                const MAX_LIMIT = 6;
                return {
                    getTopValue() {
                        return undoStack.peek();
                    },
                    addRecord(data) {
                        if (undoStack.size() >= MAX_LIMIT) {
                            undoStack.shift();
                        }
                        undoStack.push(data);
                        rollbackStack.clear();
                    },
                    undoRecord() {
                        if (undoStack.empty()) return;
                        const data = undoStack.pop();
                        rollbackStack.push(data);
                    },
                    rollbackRecord() {
                        if (rollbackStack.empty()) return;
                        const data = rollbackStack.pop();
                        undoStack.push(data);
                    },
                    getUndoStack() {
                        return undoStack.getList();
                    },
                    getrollbackStack() {
                        return rollbackStack.getList();
                    }
                }
            }

            function createStack() {
                var list = [];
                return {
                    /**
                     * 入栈
                     * @param {*} data
                     */
                    push(data) {
                        list.push(data);
                    },

                    /**
                     * 出栈
                     */
                    pop() {
                        return list.pop();
                    },

                    size() {
                        return list.length;
                    },

                    empty() {
                        return list.length === 0;
                    },

                    clear() {
                        list = [];
                    },

                    shift() {
                        list.shift();
                    },

                    peek() {
                        return list[list.length - 1];
                    },

                    getList() {
                        return list;
                    }
                }
            }
        }

    </script>
</body>

</html>